import http from '@ohos.net.http'
import router from '@ohos.router'
import promptAction from '@ohos.promptAction'
import { Auth } from './Auth'
import { Logger } from './Logger'

// 基础地址
export const BASE_URL = 'https://api-harmony-teach.itheima.net/hm'

const req = http.createHttp()
const request = <T = unknown>(url: string, method: http.RequestMethod = http.RequestMethod.GET, params: object = {}) => {
  // 1. 拼接地址
  let fullPath = BASE_URL + url
  // 2. 创建传递的数据对象
  const options: http.HttpRequestOptions = {
    // 2.1 请求头
    header: {
      'Content-Type': 'application/json'
    },
    // 2.2 请求超时时间
    readTimeout: 30000,
    // 2.3 请求方式
    method
  }
  // 3. 判断请求方式
  if (method === http.RequestMethod.GET) {
    // 如果是get请求
    // {name: zs, age: 18} => name=zs&age=18
    // ['name', 'age'] => ['name=zs', 'age=18']
    const str = Object.keys(params).map(key => {
      return `${key}=${params[key]}`
    }).join('&')
    fullPath += `?${str}`
  } else {
    // 其它的请求(post, put, delete)
    options.extraData = params
  }

  // 4. 请求头携带token
  const user = Auth.getUser()
  if (user?.token) {
    options.header['Authorization'] = `Bearer ${user.token}`
  }

  Logger.info(`REQUEST→${url}→${method}`, JSON.stringify(params))


  // 5. 返回请求的结果
  return req.request(fullPath, options)
    .then((res) => {

      if(res.result){

        // 响应日志输出
        // 最大字符是1024
        Logger.info(`RESPONSE→${url}→${method}`, res.result.toString().substring(0, 250))

        // 5.1 处理响应式数据
        const response = JSON.parse(res.result as string) as {
          code: number
          message: string
          data: T  // 类型是由调用接口的地方传入的, 所以这里用一个泛型
        }
        // 5.2 判断业务是否成功
        // 请求成功但业务失败(code不等于10000); 请求成功业务成功(code等于10000)
        if(response.code === 10000){
          return response
        }

        // 5.4 判断登录失效
        if(response.code === 401){
          // 删除用户信息
          Auth.delUser()
          // 跳转到登录页
          // 存在问题: 如果一个页面中有同时发出多个请求, 会往页面栈中加入多个登录页面
          // 如何处理: 保证页面栈中只有一个登录页面 -> 保持单路由模式
          router.pushUrl({
            url: 'pages/Login'
          }, router.RouterMode.Single)
        }

        // 5.3 其它情况 请求成功但业务失败
        return Promise.reject(res.result)
      }
    })
    .catch((e) => {
      // 错误日志输出
      Logger.error(`RESPONSE→${url}→${method}`, JSON.stringify(e).substring(0, 250))
      promptAction.showToast({message: '网络错误'})
      return Promise.reject(e)
    })
    .finally(() => {
       // 释放请求资源
       req.destroy()
    })
}

export class Request {
  static get<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.GET, params)
  }

  static post<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.POST, params)
  }

  static put<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.PUT, params)
  }

  static delete<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.DELETE, params)
  }
}